package gamelogic

import (
	"server_cluster/common/config"
	"server_cluster/common/gdconf"
	"server_cluster/common/logger"
	"server_cluster/common/mysock"
	"server_cluster/common/protoc/pb"
	"server_cluster/logic/sharemem"
	"strconv"
	"strings"
	"unicode/utf8"
)

func AddExp4CurTeam(totalAddExp int32, user *sharemem.User) int32 {
	var pTeam = user.GetTeam(user.GetActiveTeamId())
	if pTeam == nil {
		return config.SERVER_ERROR
	}
	var teamList = make([]int32, 0)
	teamList = append(teamList, pTeam.GetFightRoleList()...)
	teamList = append(teamList, pTeam.GetAssistRoleList()...)
	return AddExp4RoleList(totalAddExp, teamList, user)
}

func AddExp4RoleList(totalAddExp int32, teamList []int32, user *sharemem.User) int32 {
	for _, v := range teamList {
		if v == 0 {
			continue
		}
		var role = user.GetRoleById(v)
		if role == nil {
			continue
		}
		var ret = role.AddExp(totalAddExp)
		if ret != config.OK {
			logger.Error("AddExp Failed roleId:v% userId :v", v, user.GetUid())
		}
		SendMsg(config.SC_RoleUpdateNtf, &pb.SC_RoleUpdateNtf{Role: user.PacketUserRole(role)}, nil, user)
	}
	TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_ROLE_LEVEL, true)
	return config.OK
}

//=========消息协议处理=========

func TeamRoleChangeReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_TeamRoleChangeReq, new(pb.CS_TeamRoleChangeReq), buf, user).(*pb.CS_TeamRoleChangeReq)
	if !ok {
		return config.PROTO_ERROR
	}

	team := user.GetTeam(req.TeamId)
	if team == nil {
		logger.Error("get team is nil, teamId:%v, uid: %v", req.TeamId, user.GetUid())
		return SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.OBJECT_NOT_FOUND}, buf, user)
	}
	if req.RoleId != 0 {
		role := user.GetRoleById(req.RoleId)
		if role == nil {
			logger.Error("role not exist, roleId:%v, uid: %v", req.RoleId, user.GetUid())
			return SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.OBJECT_NOT_FOUND}, buf, user)
		}
	}
	if req.RoleIndex < 0 || req.RoleIndex > 5 {
		logger.Error("role index error, roleIndex: %v, uid: %v", req.RoleIndex, user.GetUid())
		return SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.SERVER_ERROR}, buf, user)
	}
	var unlockLevel = gdconf.GetConstIntList("AUXILIARYUNLOCK")
	assistIndex := req.RoleIndex - int32(len(team.GetFightRoleList()))
	if assistIndex >= 0 && assistIndex < int32(len(unlockLevel)) {
		if int32(user.Level) < unlockLevel[assistIndex] {
			return SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.LEVEL_NOT_ENOUGH}, buf, user)
		}
	}

	roleIdList := make([]int32, 0)
	roleIdList = append(roleIdList, team.GetFightRoleList()...)
	roleIdList = append(roleIdList, team.GetAssistRoleList()...)
	if req.RoleId != 0 {
		// 上阵角色
		targetRoleId := roleIdList[req.RoleIndex]
		if targetRoleId == 0 {
			// 目标位置没有角色
			for index, roleId := range roleIdList {
				if roleId == req.RoleId {
					// 清除老位置可能存在的该角色
					roleIdList[index] = 0
				}
			}
		} else {
			// 目标位置有角色
			for index, roleId := range roleIdList {
				if roleId == req.RoleId {
					// 交换位置
					roleIdList[index] = roleIdList[req.RoleIndex]
					break
				}
			}
		}
	}
	roleIdList[req.RoleIndex] = req.RoleId
	if team.GetId() == user.TeamId && roleIdList[0] == 0 && roleIdList[1] == 0 && roleIdList[2] == 0 && roleIdList[3] == 0 {
		logger.Error("active team fight role not allow be empty, uid: %v", user.GetUid())
		return SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.SERVER_ERROR}, buf, user)
	}

	team.SetFightRoleList(roleIdList[0:4])
	team.SetAssistRoleList(roleIdList[4:6])
	team.SetSync()

	TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_TEAM_ROLE_NUM, true)

	return SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.OK, Team: user.PacketPbTeamData()}, buf, user)
}

func TeamNameChangeReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_TeamNameChangeReq, new(pb.CS_TeamNameChangeReq), buf, user).(*pb.CS_TeamNameChangeReq)
	if !ok {
		return config.PROTO_ERROR
	}

	team := user.GetTeam(req.TeamId)
	if team == nil {
		logger.Error("get team is nil, teamId:%v, uid: %v", req.TeamId, user.GetUid())
		return SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.OBJECT_NOT_FOUND}, buf, user)
	}
	if utf8.RuneCountInString(req.Name) > len(team.Name) {
		logger.Error("team name too long, name: %v, uid: %v", req.Name, user.GetUid())
		return SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.SERVER_ERROR}, buf, user)
	}
	team.SetName(req.Name)
	team.SetSync()

	return SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.OK, Team: user.PacketPbTeamData()}, buf, user)
}

func TeamSetActiveReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_TeamSetActiveReq, new(pb.CS_TeamSetActiveReq), buf, user).(*pb.CS_TeamSetActiveReq)
	if !ok {
		return config.PROTO_ERROR
	}

	team := user.GetTeam(req.ActiveTeamId)
	if team == nil {
		logger.Error("get team is nil, teamId:%v, uid: %v", req.ActiveTeamId, user.GetUid())
		return SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.OBJECT_NOT_FOUND}, buf, user)
	}
	fightRoleList := team.GetFightRoleList()
	if fightRoleList[0] == 0 && fightRoleList[1] == 0 && fightRoleList[2] == 0 && fightRoleList[3] == 0 {
		logger.Error("active team fight role not allow be empty, uid: %v", user.GetUid())
		return SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.SERVER_ERROR}, buf, user)
	}

	user.SetActiveTeamId(req.ActiveTeamId)

	return SendMsg(config.SC_TeamUpdateNtf, &pb.SC_TeamUpdateNtf{RetCode: config.OK, Team: user.PacketPbTeamData()}, buf, user)
}

func TeamUnlockReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_TeamUnlockReq, new(pb.CS_TeamUnlockReq), buf, user).(*pb.CS_TeamUnlockReq)
	if !ok {
		return config.PROTO_ERROR
	}
	_ = req

	teamNum := len(user.GetTeamList())
	initTeamNum := gdconf.GetConstInt("TEAMINITIALNUM")
	maxTeamNum := gdconf.GetConstInt("TEAMMAXNUM")
	if teamNum >= int(maxTeamNum) {
		logger.Error("max team num limit, uid: %v", user.GetUid())
		return SendMsg(config.SC_TeamUnlockRsp, &pb.SC_TeamUnlockRsp{RetCode: config.SERVER_ERROR}, buf, user)
	}
	costItemMap := make(map[int32]int32)
	str := gdconf.GetConstStr("TEAMUNLOCK")
	for unlockTeamCount, str1 := range strings.Split(str, ";") {
		if unlockTeamCount+1 != teamNum-int(initTeamNum)+1 {
			continue
		}
		str2 := strings.Split(str1, "|")
		itemId, _ := strconv.Atoi(str2[0])
		ItemCount, _ := strconv.Atoi(str2[1])
		costItemMap[int32(itemId)] += int32(ItemCount)
		break
	}
	ok = CostItems(costItemMap, user)
	if !ok {
		logger.Error("cost item error, costItemMap: %v, uid: %v", costItemMap, user.GetUid())
		return SendMsg(config.SC_TeamUnlockRsp, &pb.SC_TeamUnlockRsp{RetCode: config.ITEM_NOT_ENOUGH}, buf, user)
	}
	team := user.AddTeam()
	if team == nil {
		logger.Error("add team fail, uid: %v", user.GetUid())
		return SendMsg(config.SC_TeamUnlockRsp, &pb.SC_TeamUnlockRsp{RetCode: config.SERVER_ERROR}, buf, user)
	}

	return SendMsg(config.SC_TeamUnlockRsp, &pb.SC_TeamUnlockRsp{RetCode: config.OK, Team: team.PacketPbTeam()}, buf, user)
}
